﻿using System;
using System.Threading;
using Ibp.Service.Entity.ODAEntity;
using OdaOperation.Core.Parameters;
using OdaOperation.Extends;
using Teigha.Core;
using Teigha.TD;

namespace OdaOperation.Core.Creators
{
    public class BlockReferenceCreator : BaseCreator
    {
        private OdDbObjectId m_block;

        private string m_blockName;

        public BlockReferenceCreator(OdDbDatabase pDb)
            : base(pDb)
        {
        }

        protected BlockReferenceCreator(OdDbDatabase pDb, OdDbObjectId blockTableRecord)
            : base(pDb, blockTableRecord)
        {
        }

        protected BlockReferenceCreator(OdDbDatabase pDb, string layerName)
            : base(pDb, layerName)
        {
        }

        public BlockReferenceCreator(OdDbDatabase pDb, OdDbObjectId blockTableRecordId, string layerName, OdDbObjectId block = null)
            : base(pDb, blockTableRecordId, layerName)
        {
            m_block = block;
        }

        public BlockReferenceCreator(OdDbDatabase pDb, string blockName, string layerName, OdDbObjectId block = null)
            : base(pDb, layerName)
        {
            m_block = block;
            m_blockName = blockName;
        }

        public void Create(ReferenceParameter paramter)
        {
            Create(paramter.Location.ToGePoint3D(), paramter.Scale, paramter.Rotating, paramter.MirrorPlane, paramter.Parameters, paramter.ExtendId);
        }

        public void Create(OdGePoint3d location, OdGeScale3d odGeScale = null, double rotating = 0.0, OdGePlane mirrorPlane = null, ParameterSet paramters = null, string extendId = null)
        {
            MemoryTransaction value = MemoryManager.GetMemoryManager().StartTransaction(Thread.CurrentThread.ManagedThreadId);
            OdDbObjectId odDbObjectId;
            try
            {
                if (m_blockTableId == null || !m_blockTableId.isValid())
                {
                    if (string.IsNullOrWhiteSpace(m_blockName))
                    {
                        throw new ArgumentException("被设置的blockTableId或blockName:" + m_blockName + "无效");
                    }

                    m_blockTableId = (m_database.getBlockTableId().safeOpenObject(OpenMode.kForRead) as OdDbBlockTable).getAt(m_blockName);
                }

                odDbObjectId = CreateBlockReference();
                OdDbBlockReference odDbBlockReference = odDbObjectId.openObject(OpenMode.kForWrite) as OdDbBlockReference;
                odDbBlockReference.setLayer(m_layerName, doSubents: true);
                odDbBlockReference.setPosition(location);
                odDbBlockReference.SetExtendId(extendId);
                if (rotating != 0.0)
                {
                    odDbBlockReference.setRotation(rotating);
                }

                if (odGeScale != null)
                {
                    odDbBlockReference.setScaleFactors(odGeScale);
                }

                if (mirrorPlane != null)
                {
                    OdGeMatrix3d odGeMatrix3d = new OdGeMatrix3d();
                    odGeMatrix3d.setToMirroring(mirrorPlane);
                    odDbBlockReference.transformBy(odGeMatrix3d);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            MemoryManager.GetMemoryManager().StopTransaction(value);
            if (paramters != null && paramters.Count != 0)
            {
                (odDbObjectId.openObject(OpenMode.kForWrite) as OdDbBlockReference).SetParameter(paramters);
            }
        }

        private OdDbObjectId CreateBlockReference()
        {
            OdDbBlockReference odDbBlockReference = OdDbBlockReference.createObject();
            odDbBlockReference.setDatabaseDefaults(m_database);
            odDbBlockReference.setBlockTableRecord(m_blockTableId);
            return (m_block != null && m_block.isValid()) ? (m_block.openObject(OpenMode.kForWrite) as OdDbBlockTableRecord).appendOdDbEntity(odDbBlockReference) : (GetActiveBlock().openObject(OpenMode.kForWrite) as OdDbBlockTableRecord).appendOdDbEntity(odDbBlockReference);
        }

        public void Create(DPoint point)
        {
            Create(point.ToGePoint3D());
        }
    }
}
